// Copyright (c) 2011 The Kiwii Authors. All rights reserved.
// Use of this source code is governed by the New BSD License that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.

#include "net/Event.hxx"
#include <boost/assert.hpp>
using namespace kiwii::net;

int TimeEvent::nextTimerId_ = 0;

TimeEvent::TimeEvent(long long milliseconds, TimeEventHandler const& handler) : id_(nextTimerId_++), handler_(handler) {
  setExpireTime(milliseconds);
}

void TimeEvent::setExpireTime(long long milliseconds) {
  BOOST_ASSERT(milliseconds > 0);

  struct timeval tv;
  gettimeofday(&tv, NULL);
  whenSeconds_ = milliseconds / 1000 + tv.tv_sec;
  whenMilliseconds_ = milliseconds % 1000 + tv.tv_usec / 1000;
  if (whenMilliseconds_ >= 1000) {
    whenSeconds_++;
    whenMilliseconds_ -= 1000;
  }
}

struct timeval TimeEvent::timeout() const {
  struct timeval now;
  gettimeofday(&now, NULL);

  struct timeval result;
  result.tv_sec = whenSeconds_ - now.tv_sec;
  if (whenMilliseconds_ < now.tv_usec / 1000) {
    result.tv_usec = (whenMilliseconds_ + 1000) * 1000 - now.tv_usec;
    result.tv_sec--;
  } else {
    result.tv_usec = whenMilliseconds_ * 1000 - now.tv_usec;
  }

  if (result.tv_sec < 0) result.tv_sec = 0;
  if (result.tv_usec < 0) result.tv_usec = 0;

  return result;
}

bool TimeEvent::isExpired() const {
  struct timeval now;
  gettimeofday(&now, NULL);

  if (whenSeconds_ < now.tv_sec)
    return true;
  else if (whenSeconds_ == now.tv_sec) {
    if (whenMilliseconds_ <= now.tv_usec / 1000)
      return true;
    else
      return false;
  } else 
    return false;
}
